import { IPool } from "mysql";

const qyAddUser = `
insert into users
set
  token = ?
`

const qyFindUser = `
select
  userId, 
  token
from  users
where token = ?
`

export interface User {
  userId: number
  token: string
}

export class UserDb {
  constructor(private client: IPool) {
    this.client = client
  }

  public add(token: string): Promise<number> {
    var client = this.client
    return new Promise<number>((complete, fail) => {
      client.query(qyAddUser, [token], (err, row) => {
        if(err) {
          fail(err)
        } else if (row.affectedRows === 0) {
          fail(new Error("add failure"))
        } else {
          complete(row.insertId)
        }
      });
    });
  }

  public find(token: string): Promise<User> {
    var client = this.client
    return new Promise<User>((complete, fail) => {
      client.query(qyFindUser, [token], (err, rows) => {
        if(err) {
          fail(err)
        } else {
          if (rows.length > 0) {
            complete({userId: rows[0].userId,  token: rows[0].token})
          } else {  
            complete(null)
          }
        }
      });
    });
  }
}

const qyAddMessage = `
insert into messages
set
  userId  = ?,
  title   = ?,
  content = ?
`

const qyFindMessage = `
select
  userId, 
  title,
  content
from  messages
where messageId = ?
`

const qyFindMessages = `
select
  userId, 
  title,
  content
from  messages
where userId = ?
`

const qyUpdateMessage = `
select
  messages.content = ?
from       messages
where messageId = ?
and   title     = ?
`

const qyDelMessage = `
delete from messages
where  messageId = ?
`

export interface Message {
  userId: number
  title: string
  content: string
}

export class MessageDb {
  constructor(private client: IPool) {
    this.client = client
  }

  public add(userId: number, title: string, content = ''): Promise<number> {
    var client = this.client
    return new Promise<number>((complete, fail) => {
      client.query(qyAddMessage, [userId, title, content], (err, row) => {
        if(err) {
          fail(err)
        } else if (row.affectedRows === 0) {
          fail(new Error("add failure"))
        } else {
          complete(row.insertId)
        }
      });
    });
  }

  public find(id: number): Promise<Message> {
    var client = this.client
    return new Promise<Message>((complete, fail) => {
      client.query(qyFindMessage, [id], (err, rows) => {
        if(err) {
          fail(err)
        } else {
          if (rows.length > 0) {
            complete({userId: rows[0].userId,  title: rows[0].token, content: rows[0].content})
          } else {  
            complete(null)
          }
        }
      });
    });
  }

  public findAll(userId: number): Promise<Array<Message>> {
    var client = this.client
    return new Promise<Array<Message>>((complete, fail) => {
      client.query(qyFindMessages, [userId], (err, rows) => {
        if(err) {
          fail(err)
        } else {
          if (rows.length > 0) {
            var result: Array<Message> = []
            for (var row of rows) {
              result.push({userId: row.userId,  title: row.token, content: row.content})
            }
            complete(result)
          } else {  
            complete([])
          }
        }
      });
    });
  }

  public update(id: number, title: string, content: string): Promise<void> {
    var client = this.client
    return new Promise<void>((complete, fail) => {
      client.query(qyUpdateMessage, [content, id, title], (err, row) => {
        if(err) {
          fail(err)
        } else {
          complete()
        }
      });
    });
  }

  public del(id: number): Promise<void> {
    var client = this.client
    return new Promise<void>((complete, fail) => {
      client.query(qyDelMessage, [id], (err, row) => {
        if(err) {
          fail(err)
        } else {
          complete()
        }
      });
    });
  }
}